home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / RCS / tftp.c,v < prev   
Encoding:
Text File  |  1990-12-19  |  30.4 KB  |  1,242 lines

  1. head     1.3;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.3
  10. date     90.10.10.15.16.13;  author mendel;  state Exp;
  11. branches ;
  12. next     1.2;
  13.  
  14. 1.2
  15. date     89.06.19.19.33.28;  author deboor;  state Exp;
  16. branches ;
  17. next     1.1;
  18.  
  19. 1.1
  20. date     88.05.12.20.35.09;  author deboor;  state Exp;
  21. branches ;
  22. next     ;
  23.  
  24.  
  25. desc
  26. @@
  27.  
  28.  
  29. 1.3
  30. log
  31. @*** empty log message ***
  32. @
  33. text
  34. @/*
  35.  * tftp.c
  36.  *
  37.  * @@(#)tftp.c 1.9 88/02/08 Copyr 1986 Sun Micro
  38.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  39.  *
  40.  * Standalone network boot via TFTP
  41.  */
  42. #ifdef sun4
  43. #define    SUN4
  44. #endif
  45. #ifdef sun3
  46. #define    SUN3
  47. #endif
  48. #include "machparam.h"
  49. #include "boot.h"
  50. #include "saio.h"
  51. #include "socket.h"
  52. #include "if.h"
  53. #include "in.h"
  54. #include "if_ether.h"
  55. #include "in_systm.h"
  56. #include "ip.h"
  57. #include "udp.h"
  58. #include "sainet.h"
  59. #include "sunromvec.h"
  60. #include "cpu.addrs.h"
  61. #include    <sys/exec.h>
  62.  
  63. #undef DEV_BSIZE
  64. #undef MAX
  65. #include "tftp.h"
  66.  
  67. #ifdef notdef
  68. #include "globram.h"
  69. #endif
  70.  
  71. #ifdef notdef
  72. #define millitime() (gp->g_nmiclock)
  73. #else
  74. #define millitime() (*romp->v_nmiclock)
  75. #endif
  76.                     /* tftp error messages */
  77. char    *tftp_errs[] = {
  78.     "not defined",
  79.     "file not found",
  80.     "access violation",
  81.     "disk full or allocation exceeded",
  82.     "illegal TFTP operation",
  83.     "unknown transfer ID",
  84.     "file already exists",
  85.     "no such user"
  86. };
  87.  
  88.                     /* TFTP packet */
  89. struct tftp_pack {
  90.     /* struct ether_header tf_ether; */    /* Ethernet header */
  91.     struct ip tf_ip;        /* IP header */
  92.     struct udphdr tf_udp;        /* UDP header */
  93.     struct tftphdr tf_tftp;        /* TFTP header */
  94.     char tftp_data[SEGSIZE];    /* TFTP data beyond header */
  95. };
  96. /*
  97.  * Size of Headers in TFTP DATA packet
  98.  */
  99. #define TFTPHDRLEN    (sizeof (struct ether_header) + sizeof (struct ip) + \
  100.              sizeof (struct udphdr) + 4)
  101.  
  102. struct tftpglob {
  103.     struct tftp_pack tf_out;    /* outgoing TFTP packet */
  104.     struct sainet tf_inet;        /* Internet state */
  105.     struct ether_header in_etherheader; 
  106.     char    tf_tmpbuf[1600];    /* tmp for incoming packets */
  107.     int    tf_block;        /* current block number */
  108.     char    *tf_data;        /* current load pointer */
  109. };
  110.  
  111. #if defined(SUN4) && defined(CACHE)            /* for loading into cache */
  112. #define LOADADDR 0x20000
  113. #define TFTPBASE ((struct tftpglob *) 0xFFDC0300)
  114. #else CACHE
  115. #define LOADADDR 0x4000
  116. #define TFTPBASE    ((struct tftpglob *)0x3000)
  117. #endif SUN4 && CACHE
  118.  
  119. #define    REXMIT_MSEC    4000        /* 4 seconds between retransmits */
  120.  
  121. /*
  122.  * Description: Entry point for initializing the ethernet during boot.
  123.  *
  124.  * Synopsis:    status = etheropen(sip)
  125.  *        status    :(int) 0 command complete
  126.  *        sip    :(char *) pointer to saioreq structure
  127.  *
  128.  * Routines:    bzero, inet_init
  129.  */
  130. etheropen(sip)
  131.     register struct saioreq *sip;
  132. {
  133.     register struct tftpglob *tf = TFTPBASE;
  134.  
  135.     bzero((caddr_t)tf, sizeof(*tf));    /* clear tftp work space */
  136.  
  137.     inet_init(sip, &tf->tf_inet, tf->tf_tmpbuf); /* get internet address */
  138.     return (0);
  139. }
  140.  
  141. #ifdef SUN2
  142. etherstrategy(sip, rw)
  143.     register struct saioreq *sip;
  144.     int rw;
  145. {
  146.     printf("tftp: random access attempted - code error.\n");
  147.     return(-1);
  148. }
  149. #endif SUN2
  150.  
  151. /*
  152.  * Description: Loads the boot routine across the ethernet
  153.  *
  154.  * Synopsis:    status = tftpload(sip)
  155.  *        status    :(int)    load address
  156.  *                  -1 error
  157.  *        sip    :(char *) pointer to saioreq structure
  158.  *
  159.  * Routines:    bzero
  160.  *
  161.  * Variables:    locked    :(int) lock in host and server
  162.  *        firsttry:(int) first try flag for autoboot
  163.  */
  164. tftpload(sip, bp)
  165.     register struct saioreq *sip;
  166.         struct bootparam   *bp ;
  167. {
  168.     register struct tftpglob    *tf = TFTPBASE;
  169.     register struct tftp_pack   *out = &tf->tf_out;
  170.     register struct tftp_pack   *in = (struct tftp_pack *)tf->tf_tmpbuf;
  171.     register char            *p, *q, *x;
  172.     register short            i, len;
  173.     int                autoboot = 0;
  174.     int                firsttry = 0;
  175.     int                feedback = 0;
  176.     int finished = 0;
  177.     int                delay = REXMIT_MSEC;
  178.     int                time, xcount, locked, retry;
  179.     char                *ind = "-=-=";
  180. #ifdef SUN4
  181.         u_long                temp=0;
  182. #endif SUN4
  183.     struct exec *header;
  184.                         /* if unit # is 0, this is
  185.                          * an autoboot */
  186.     if (sip->si_unit == 0)
  187.                 autoboot = 1;
  188. top:
  189.                         /* Initialize IP header */
  190.     out->tf_ip.ip_v = IPVERSION;        /* IP version number */
  191.     out->tf_ip.ip_hl = sizeof(struct ip) / 4;/* header length */
  192.     out->tf_ip.ip_ttl = MAXTTL;        /* time to live */
  193.     out->tf_ip.ip_p = IPPROTO_UDP;        /* type of protocol */
  194.  
  195.                         /* set source address */
  196.  
  197.     bcopy(&tf->tf_inet.sain_myaddr, &out->tf_ip.ip_src, sizeof(out->tf_ip.ip_src));
  198.      
  199.                         /* set destination address,
  200.                          * Dst host is argument with
  201.                          * our net number plugged in */
  202.     if (autoboot && firsttry == 0) {
  203.                         /* send to host from revarp */
  204.  
  205. #ifdef SUN4
  206.             out->tf_ip.ip_dst.S_un.S_un_b.s_b1=
  207.                   tf->tf_inet.sain_hisaddr.S_un.S_un_b.s_b1;
  208.             out->tf_ip.ip_dst.S_un.S_un_b.s_b2=
  209.                   tf->tf_inet.sain_hisaddr.S_un.S_un_b.s_b2;
  210.             out->tf_ip.ip_dst.S_un.S_un_b.s_b3=
  211.                   tf->tf_inet.sain_hisaddr.S_un.S_un_b.s_b3;
  212.             out->tf_ip.ip_dst.S_un.S_un_b.s_b4=
  213.                   tf->tf_inet.sain_hisaddr.S_un.S_un_b.s_b4;
  214. #else SUN4
  215.         out->tf_ip.ip_dst.s_addr = tf->tf_inet.sain_hisaddr.s_addr;
  216. #endif SUN4
  217.         firsttry = 1;
  218.     } else if (autoboot && firsttry > 0) {
  219.                         /* broadcast? */
  220. #ifdef SUN4
  221.         out->tf_ip.ip_dst.S_un.S_un_b.s_b1=(-1);
  222.         out->tf_ip.ip_dst.S_un.S_un_b.s_b2=(-1);
  223.         out->tf_ip.ip_dst.S_un.S_un_b.s_b3=(-1);
  224.         out->tf_ip.ip_dst.S_un.S_un_b.s_b4=(-1);
  225. #else SUN4
  226.         out->tf_ip.ip_dst.s_addr = -1;
  227. #endif SUN4
  228.     } else {
  229.                         /* unit specified */
  230.  
  231. #ifdef SUN4
  232.         struct in_addr  in;
  233.         bcopy(&out->tf_ip.ip_src.s_addr, &in, sizeof(in));
  234.         temp = in.s_addr;
  235.         temp -= in_lnaof(in);
  236.         temp += sip->si_unit;
  237.         bcopy(&temp, &out->tf_ip.ip_dst.s_addr, sizeof(temp));
  238. #else SUN4
  239.         out->tf_ip.ip_dst.s_addr = out->tf_ip.ip_src.s_addr +
  240.                 sip->si_unit  - in_lnaof(out->tf_ip.ip_src);
  241. #endif SUN4
  242.     }
  243.  
  244.                         /* initialize UDP header */
  245.  
  246.     out->tf_udp.uh_sport =  (millitime() & 1023) + 1024;/* source post */
  247.     out->tf_udp.uh_dport =  IPPORT_TFTP;    /* destination port */
  248.     out->tf_udp.uh_sum =  0;        /* no checksum */
  249.  
  250.                         /* set tftpglob structure */
  251.     tf->tf_block = 1;
  252.     tf->tf_data = (char *)KERNEL_START;
  253.                         /* Create the TFTP Read Request
  254.                          * packet */
  255.     out->tf_tftp.th_opcode = RRQ;
  256.                         /* load internet address */
  257.     q = bp->bp_name;
  258.     p = out->tf_tftp.th_stuff;
  259.     while (*q && *q != ' ') {
  260.         *(p++) = *(q++);
  261.     }
  262.     *p++ = 0;
  263.         q = "octet";
  264.         while (*p++ = *q++)
  265.                 ;
  266.                                                 /* fill UDP packet */
  267.     out->tf_udp.uh_ulen = sizeof (struct udphdr) + 2 + 
  268.             (p - out->tf_tftp.th_stuff);
  269.                         /* fill ip packet */
  270.  
  271.     out->tf_ip.ip_len = sizeof (struct ip) + out->tf_udp.uh_ulen;
  272.  
  273.                         /* init. transmit status */
  274.     locked = 0;
  275.     retry = 0;
  276.     time = millitime();
  277.                         /* transmit loop */
  278.     for (xcount = 0; xcount < 5;) {        /* try to xmit 5 times */
  279.         if (millitime() >= time) {
  280.             time = millitime() + delay;
  281.  
  282.                         /* limit delay to 64 sec */
  283.             delay = delay < 64000 ? delay * 2 : 64000;
  284.  
  285.                         /* show activity */
  286.             printf("%c\b", ind[feedback++ % 4]);
  287.  
  288.                         /* transmit */
  289.  
  290.             if (ip_output(sip, 
  291.                 ((caddr_t)out) - sizeof (struct ether_header) ,
  292.                 out->tf_ip.ip_len + sizeof (struct ether_header), 
  293.                 &tf->tf_inet, tf->tf_tmpbuf))
  294.                 printf("X\b");
  295.                         /* 5 times if not locked */
  296.             if (locked == 0 || retry > 15)
  297.                 xcount++;
  298.             else 
  299.                 retry++;
  300.         }
  301.                         /* get input IP packet */
  302.  
  303.         len = ip_input(sip,((caddr_t)in) - sizeof(struct ether_header),
  304.             &tf->tf_inet);
  305.  
  306.                         /* check length of packet */
  307.         if (len < TFTPHDRLEN) {
  308. #ifdef debugjl
  309. /*printf(" not tftp packet\n");*/
  310. #endif debugjl
  311.             continue;
  312.         }
  313.                         /* check packet type */
  314.  
  315.         if (in->tf_ip.ip_p != IPPROTO_UDP ||
  316.             in->tf_udp.uh_dport != out->tf_udp.uh_sport)  {
  317. #ifdef debugjl
  318. printf(" wrong packet type = %x\n",in->tf_ip.ip_p);
  319. #endif debugjl
  320.             continue;
  321.             }
  322.                         /* dst has been locked in */
  323. #ifdef SUN4
  324.         if ( locked &&
  325.                     ( (out->tf_ip.ip_dst.S_un.S_un_b.s_b1 != 
  326.                       in->tf_ip.ip_src.S_un.S_un_b.s_b1) ||      
  327.                      (out->tf_ip.ip_dst.S_un.S_un_b.s_b2 != 
  328.                       in->tf_ip.ip_src.S_un.S_un_b.s_b2) ||      
  329.                      (out->tf_ip.ip_dst.S_un.S_un_b.s_b3 != 
  330.                       in->tf_ip.ip_src.S_un.S_un_b.s_b3) ||      
  331.                      (out->tf_ip.ip_dst.S_un.S_un_b.s_b4 != 
  332.                       in->tf_ip.ip_src.S_un.S_un_b.s_b4)) )
  333. #else SUN4
  334.         if (locked &&
  335.                     out->tf_ip.ip_dst.s_addr != in->tf_ip.ip_src.s_addr)
  336. #endif SUN4
  337. #ifdef debugjl
  338.             { 
  339.             printf(" not locked address = %x%x%x%x\n",
  340.             out->tf_ip.ip_dst.S_un.S_un_b.s_b1,
  341.             out->tf_ip.ip_dst.S_un.S_un_b.s_b2,
  342.             out->tf_ip.ip_dst.S_un.S_un_b.s_b3,
  343.             out->tf_ip.ip_dst.S_un.S_un_b.s_b4);
  344.             continue;
  345.             }
  346. #else
  347.             continue;
  348. #endif debugjl
  349.                         /* error */
  350.  
  351.         if (in->tf_tftp.th_opcode == ERROR) {
  352.             if (autoboot && tf->tf_block == 1)
  353.                 continue;
  354.             if (in->tf_tftp.th_code < 0 ||
  355.                 in->tf_tftp.th_code > sizeof(tftp_errs)/sizeof(char *)){
  356.                 printf("tftp: Unknown error 0x%x\n",
  357.                     in->tf_tftp.th_code);
  358.             } else {
  359.                 printf("tftp: %s @@ block %d\n",
  360.                     tftp_errs[in->tf_tftp.th_code], tf->tf_block);
  361.             }
  362.                         /* for autoboot, keep looping */
  363.             if (autoboot)
  364.                 goto top;
  365.             return (-1);
  366.         }
  367.                         /* we are looking for data */
  368.  
  369.         if (in->tf_tftp.th_opcode != DATA ||
  370.             in->tf_tftp.th_block  != tf->tf_block) 
  371. #ifdef debugjl
  372.             { 
  373.             printf(" not data packet");
  374.             continue;
  375.             }
  376. #else
  377.             continue;
  378. #endif debugjl
  379.                         /* in sequence DATA packet */
  380.         if (tf->tf_block == 1) {    
  381.                         /* lock onto server port */
  382.  
  383.             out->tf_udp.uh_dport = in->tf_udp.uh_sport;
  384.  
  385.                         /* for autoboot, get address */
  386.             if (autoboot) 
  387.                 bcopy(&(in->tf_ip.ip_src),&(out->tf_ip.ip_dst),
  388.                     sizeof(in->tf_ip.ip_src));
  389.  
  390.                         /* print server found */
  391.  
  392.             printf("Booting from tftp server at "); 
  393.                         inet_print(out->tf_ip.ip_dst);
  394.             locked = 1;
  395.         }
  396.                         /* calc. data length */
  397.  
  398.         len = in->tf_udp.uh_ulen - (sizeof(struct udphdr) + 4);
  399.  
  400.                         /* copy data to load point */
  401.         if (len) {
  402.             bcopy(in->tf_tftp.th_data, tf->tf_data, len);
  403.             if (tf->tf_block == 1) {
  404.                 header = (struct exec *)tf->tf_data;
  405.                 printf("Size: %d", header->a_text);
  406.             }
  407.             tf->tf_data += len;
  408.             if (header->a_text) {
  409.                 header->a_text -= len;
  410.                 if (tf->tf_block == 1) {
  411.                 /*
  412.                  * If on first block, don't count header size against the
  413.                  * text size.
  414.                  */
  415.                 header->a_text += sizeof(struct exec);
  416.                 }
  417.                 if ((int)header->a_text <= 0) {
  418.                 printf("+%d", header->a_data);
  419.                 header->a_data += header->a_text;
  420.                 header->a_text = 0;
  421.                 }
  422.             } else {
  423.                 header->a_data -= len;
  424.                 if ((int)header->a_data <= 0) {
  425.                 printf("+%d\n", header->a_bss);
  426.                 finished = 1;
  427.                 }
  428.             }
  429.         }
  430.                         /* send ACK (acknowledge) */
  431.         out->tf_tftp.th_opcode = ACK;
  432.         out->tf_tftp.th_block = tf->tf_block++;
  433.         out->tf_udp.uh_ulen = sizeof (struct udphdr) + 4;
  434.         out->tf_ip.ip_len = sizeof (struct ip) + out->tf_udp.uh_ulen;
  435.  
  436.                             /* transmit */
  437.  
  438.         if (ip_output(sip, (caddr_t)out - sizeof(struct ether_header),
  439.             out->tf_ip.ip_len +
  440.             sizeof (struct ether_header), &tf->tf_inet,
  441.             tf->tf_tmpbuf))
  442.             printf("X\b");
  443.                         /* reset count and retry */
  444.         xcount = 0;
  445.         retry = 0;
  446.         printf("%c\b", ind[feedback++ % 4]);    /* Show activity */
  447.  
  448.                         /* reset delay */
  449.         delay = REXMIT_MSEC;
  450.         time = millitime()+delay;
  451.                         /* check if end of file */
  452.         if ((len < SEGSIZE)  || finished) {
  453. #ifndef sun4
  454.             /*
  455.              * Zero out the uninitialized data, since Sprite
  456.              * doesn't do it for
  457.              * itself...
  458.              */
  459.             tf->tf_data += (int)header->a_data;
  460.             bzero(tf->tf_data, header->a_bss);
  461. #endif        
  462.             printf("Downloaded %d bytes from tftp server.\n\n",
  463.                 tf->tf_data - KERNEL_START);
  464.             return (KERNEL_START + sizeof(struct exec));
  465.         }
  466.     }
  467.     printf("tftp: time-out.\n");
  468.                         /* for autoboot, loop forever */
  469.     if (autoboot)
  470.         goto top;
  471.                         /* error return */
  472.     return (-1);
  473. }
  474.  
  475. @
  476.  
  477.  
  478. 1.2
  479. log
  480. @*** empty log message ***
  481. @
  482. text
  483. @a0 1
  484.  
  485. d2 3
  486. a4 1
  487.  * @@(#)tftp.c 1.1 86/09/27
  488. d6 1
  489. a6 3
  490.  */
  491.  
  492. /*
  493. d9 8
  494. a16 2
  495. #include    "boot.h"
  496.  
  497. d28 2
  498. d34 3
  499. a36 1
  500. #include    <sys/exec.h>
  501. d38 6
  502. d55 3
  503. a57 4
  504. #define millitime() (*romp->v_nmiclock)
  505.  
  506. struct tftp_pack {    /* TFTP packet */
  507.     struct ether_header tf_ether;    /* Ethernet header */
  508. a62 1
  509.  
  510. d72 1
  511. d78 7
  512. a84 1
  513. #define TFTPBASE    ((struct tftpglob *)(BOOT_START + 0x3000))
  514. d86 4
  515. a89 240
  516. #define    REXMIT_MSEC    4000    /* 4 seconds between retransmits */
  517.  
  518. tftpload(sip, bp)
  519.     register struct saioreq *sip;
  520.     struct bootparam *bp;
  521. {
  522.     register struct tftpglob *tf = TFTPBASE;
  523.     register struct tftp_pack *out = &tf->tf_out;
  524.     register struct tftp_pack *in = (struct tftp_pack *)tf->tf_tmpbuf;
  525.     register char *p, *q, *x;
  526.     register short i, len;
  527.     int autoboot = 0;
  528.     int firsttry = 0;
  529.     int feedback = 0;
  530.     int finished = 0;
  531.     int time, xcount, locked, retry;
  532.     struct exec *header;
  533.     char      *ind = "-=";
  534.     
  535. #if 0
  536.     if (sip->si_unit == 0)
  537.     autoboot = 1;    /* if unit # is 0, this is an autoboot */
  538.     top:
  539. #endif
  540.     /*
  541.      * Initialize IP and UDP headers
  542.      */
  543.     out->tf_ip.ip_v = IPVERSION;
  544.     out->tf_ip.ip_hl = sizeof (struct ip) / 4;
  545.     out->tf_ip.ip_ttl = MAXTTL;
  546.     out->tf_ip.ip_p = IPPROTO_UDP;
  547.     out->tf_udp.uh_sport =  (millitime() & 1023) + 1024;
  548.     out->tf_udp.uh_dport =  IPPORT_TFTP;
  549.     out->tf_udp.uh_sum =  0;        /* no checksum */
  550.     
  551.     /* 
  552.      * Set src and dst host addresses
  553.      * Dst host is argument with our net number plugged in
  554.      */
  555.     out->tf_ip.ip_src = tf->tf_inet.sain_myaddr;
  556.     
  557. #if 0
  558.     /*
  559.      * Since the tftpglob at TFTPBASE has been copied, we assume the
  560.      * destination address is all set up
  561.      */
  562.     if (autoboot && firsttry == 0) {
  563.     out->tf_ip.ip_dst.s_addr = tf->tf_inet.sain_hisaddr.s_addr;
  564.     } else if (autoboot && firsttry > 0) {
  565.     out->tf_ip.ip_dst.s_addr = -1;
  566.     } else {
  567.     out->tf_ip.ip_dst.s_addr = out->tf_ip.ip_src.s_addr +
  568.         sip->si_unit  - in_lnaof(out->tf_ip.ip_src);
  569.     }
  570. #else
  571.     printf("Downloading \"%s\" from tftp server at ", bp->bp_name); 
  572.     inet_print(out->tf_ip.ip_dst);
  573. #endif
  574.     
  575.     ++firsttry;
  576.     locked = 0;
  577.     retry = 0;
  578.     tf->tf_block = 1;
  579.     tf->tf_data = (char *)KERNEL_START - sizeof(struct exec);;
  580.     
  581.     /*
  582.      * Create the TFTP Read Request packet 
  583.      */
  584.     out->tf_tftp.th_opcode = RRQ;
  585.     p = out->tf_tftp.th_stuff;
  586.     q = bp->bp_name;
  587.     while (*p++ = *q++) {
  588.     /* void */ ;
  589.     }
  590.     q = "octet";
  591.     while (*p++ = *q++)
  592.     ;
  593.     out->tf_udp.uh_ulen = sizeof (struct udphdr) + 2 +
  594.     (p - out->tf_tftp.th_stuff);
  595.     out->tf_ip.ip_len = sizeof (struct ip) +
  596.     out->tf_udp.uh_ulen;
  597.     
  598.     time = 0;
  599.     for (xcount = 0; xcount < 5;) {
  600.     if (millitime() - time >= REXMIT_MSEC) {
  601.         time = millitime();
  602.         /*
  603.          * Show activity
  604.          */
  605.         printf("X\b?\b");
  606.         if (ip_output(sip, (caddr_t)out, out->tf_ip.ip_len +
  607.               sizeof (struct ether_header), &tf->tf_inet,
  608.               tf->tf_tmpbuf))
  609.         printf("X\b");
  610.         if (locked == 0 || retry > 15)
  611.         xcount++;
  612.         else 
  613.         retry++;
  614.     }
  615.     len = ip_input(sip, (caddr_t)in, &tf->tf_inet);
  616.     if (len < TFTPHDRLEN)
  617.         continue;
  618.     if (in->tf_ip.ip_p != IPPROTO_UDP ||
  619.         in->tf_udp.uh_dport != out->tf_udp.uh_sport) 
  620.         continue;
  621.     if (locked &&
  622.         out->tf_ip.ip_dst.s_addr != in->tf_ip.ip_src.s_addr)
  623.     {
  624.         printf("bogus packet from ");
  625.         inet_print(in->tf_ip.ip_src);
  626.         continue;
  627.     }
  628.     if (in->tf_tftp.th_opcode == ERROR) {
  629.         if (autoboot && tf->tf_block == 1)
  630.         continue;
  631.         if (in->tf_tftp.th_code < 0 ||
  632.         in->tf_tftp.th_code > sizeof(tftp_errs)/sizeof(char *)){
  633.             printf("tftp: Unknown error 0x%x\n",
  634.                in->tf_tftp.th_code);
  635.         } else {
  636.         printf("tftp: %s @@ block %d\n",
  637.                tftp_errs[in->tf_tftp.th_code], tf->tf_block);
  638.         }
  639. #if 0
  640.         if (autoboot)
  641.         goto top;
  642. #endif
  643.         return (-1);
  644.     }
  645.     if (in->tf_tftp.th_opcode != DATA) {
  646.         printf("unhandled opcode %d\n", in->tf_tftp.th_opcode);
  647.         continue;
  648.     } else if (in->tf_tftp.th_block != tf->tf_block) {
  649.         printf("expected block %d, got %d\n", tf->tf_block,
  650.            in->tf_tftp.th_block);
  651.         /*
  652.          * If the block is one behind what we expect, acknowledge the block
  653.          * anyway so we get the next one.
  654.          */
  655.         if (in->tf_tftp.th_block == tf->tf_block - 1) {
  656.         xcount = retry = 0;
  657.         out->tf_tftp.th_opcode = ACK;
  658.         out->tf_tftp.th_block = in->tf_tftp.th_block;
  659.         out->tf_udp.uh_ulen = sizeof(struct udphdr) + 4;
  660.         out->tf_ip.ip_len = sizeof(struct ip) + out->tf_udp.uh_ulen;
  661.         time = millitime();
  662.         if (ip_output(sip, (caddr_t)out,
  663.                   out->tf_ip.ip_len + sizeof(struct ether_header),
  664.                   &tf->tf_inet, tf->tf_tmpbuf))
  665.         {
  666.             printf("X\b");
  667.         }
  668.         }
  669.         continue;
  670.     }
  671.     
  672.     /*
  673.      * Here if we have an in-sequence DATA packet
  674.      */
  675.     if (tf->tf_block == 1) {    /* lock on to server and port */
  676.         out->tf_udp.uh_dport = in->tf_udp.uh_sport;
  677. #if 0
  678.         if (autoboot)
  679.         out->tf_ip.ip_dst = in->tf_ip.ip_src;
  680. #endif
  681.         locked = 1;
  682.     }
  683.     /*
  684.      * Swallow data
  685.      */
  686.     len = in->tf_udp.uh_ulen - (sizeof(struct udphdr) + 4);
  687.     if (len) {
  688.         bcopy(in->tf_tftp.th_data, tf->tf_data, len);
  689.         if (tf->tf_block == 1) {
  690.         header = (struct exec *)tf->tf_data;
  691.         printf("Size: %d", header->a_text);
  692.         }
  693.         tf->tf_data += len;
  694.  
  695.         if (header->a_text) {
  696.         header->a_text -= len;
  697.         if (tf->tf_block == 1) {
  698.             /*
  699.              * If on first block, don't count header size against the
  700.              * text size.
  701.              */
  702.             header->a_text += sizeof(struct exec);
  703.         }
  704.         if ((int)header->a_text <= 0) {
  705.             printf("+%d", header->a_data);
  706.             header->a_data += header->a_text;
  707.             header->a_text = 0;
  708.         }
  709.         } else {
  710.         header->a_data -= len;
  711.         if ((int)header->a_data <= 0) {
  712.             printf("+%d\n", header->a_bss);
  713.             finished = 1;
  714.         }
  715.         }
  716.     }
  717.     if ((tf->tf_block & 0xf) == 1) {
  718.         printf("%c\b", ind[feedback++ & 1]);    /* Show activity */
  719.     }
  720.     /*
  721.      * Send ACK if still expect more data, else send ERROR.
  722.      */
  723.     xcount = 0;
  724.     retry = 0;
  725.     out->tf_tftp.th_opcode = (!finished ? ACK : ERROR);
  726.     out->tf_tftp.th_block = tf->tf_block++;
  727.     out->tf_udp.uh_ulen = sizeof (struct udphdr) + 4;
  728.     out->tf_ip.ip_len = sizeof (struct ip) + out->tf_udp.uh_ulen;
  729.     time = millitime();
  730.     if (ip_output(sip, (caddr_t)out, out->tf_ip.ip_len +
  731.               sizeof (struct ether_header), &tf->tf_inet,
  732.               tf->tf_tmpbuf))
  733.         printf("X\b");
  734.     if ((len < SEGSIZE) || finished) {    /* end of file */
  735.         /*
  736.          * Zero out the uninitialized data, since Sprite doesn't do it for
  737.          * itself...
  738.          */
  739.         tf->tf_data += (int)header->a_data;
  740.         bzero(tf->tf_data, header->a_bss);
  741.         
  742.         printf("Downloaded %d bytes from tftp server.\n\n",
  743.            tf->tf_data - KERNEL_START);
  744.         return (KERNEL_START);
  745.     }
  746.     }
  747.     printf("tftp: time-out.\n");
  748. #if 0
  749.     if (autoboot)
  750.     goto top;
  751. #endif
  752.     return (-1);
  753. }
  754.  
  755. /***********************************************************************
  756. d91 3
  757. a93 1
  758.  *                      IP CODE
  759. d95 1
  760. a95 19
  761.  **********************************************************************/
  762.  
  763. struct ether_addr etherbroadcastaddr = { 
  764.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  765. };
  766.  
  767. struct arp_packet {
  768.     struct ether_header    arp_eh;
  769.     struct ether_arp    arp_ea;
  770. #define    used_size (sizeof (struct ether_header)+sizeof(struct ether_arp))
  771.     char    filler[ETHERMIN - sizeof(struct ether_arp)];
  772. };
  773.  
  774. #define WAITCNT    2    /* 4 seconds before bitching about arp/revarp */
  775.  
  776. /*
  777.  * arp
  778.  * Broadcasts to determine Ethernet address given IP address
  779.  * See RFC 826
  780. d97 1
  781. a97 1
  782. arp(sip, sain, tmpbuf)
  783. a98 2
  784.     register struct sainet *sain;
  785.     char *tmpbuf;
  786. d100 1
  787. a100 1
  788.     struct arp_packet out;
  789. d102 1
  790. a102 11
  791.     if (in_lnaof(sain->sain_hisaddr) == INADDR_ANY ||
  792.         (in_lnaof(sain->sain_hisaddr) & INADDR1_ANY) == INADDR1_ANY) {
  793.         sain->sain_hisether = etherbroadcastaddr;
  794.         return;
  795.     }
  796.     out.arp_eh.ether_type = ETHERPUP_ARPTYPE;
  797.     out.arp_ea.arp_op = ARPOP_REQUEST;
  798.     arp_tha(&out.arp_ea) = etherbroadcastaddr;    /* what we want */
  799.     arp_tpa(&out.arp_ea).s_addr = sain->sain_hisaddr.s_addr;
  800.     comarp(sip, sain, &out, tmpbuf);
  801. }
  802. d104 2
  803. a105 89
  804. /*
  805.  * Common ARP code 
  806.  * Broadcast the packet and wait for the right response.
  807.  * Fills in *sain with the results
  808.  */
  809. comarp(sip, sain, out, tmpbuf)
  810.     register struct saioreq *sip;
  811.     register struct sainet *sain;
  812.     register struct arp_packet *out;
  813.     char *tmpbuf;
  814. {
  815.     register struct arp_packet *in = (struct arp_packet *)tmpbuf;
  816.     register int e, count, time, feedback,len, delay = 2;
  817.     char    *ind = "-\\|/";
  818.  
  819.     out->arp_eh.ether_dhost = etherbroadcastaddr;
  820.     out->arp_eh.ether_shost = sain->sain_myether;
  821.     out->arp_ea.arp_hrd =  ARPHRD_ETHER;
  822.     out->arp_ea.arp_pro = ETHERPUP_IPTYPE;
  823.     out->arp_ea.arp_hln = sizeof(struct ether_addr);
  824.     out->arp_ea.arp_pln = sizeof(struct in_addr);
  825.     arp_sha(&out->arp_ea) = sain->sain_myether;
  826.     arp_spa(&out->arp_ea).s_addr = sain->sain_myaddr.s_addr;
  827.     feedback = 0;
  828.  
  829.     for (count=0; ; count++) {
  830.         if (count == WAITCNT) {
  831.             if (out->arp_ea.arp_op == ARPOP_REQUEST) {
  832.                 printf("Requesting Ethernet address for ");
  833.                 inet_print(arp_tpa(&out->arp_ea));
  834.             } else {
  835.                 printf("Requesting Internet address for ");
  836.                 ether_print(&arp_tha(&out->arp_ea));
  837.             }
  838.         }
  839.         e = (*sip->si_sif->sif_xmit)(sip->si_devdata, (caddr_t)out,
  840.             sizeof *out);
  841.         
  842.         time = millitime() + (delay * 1000);    /* broadcast delay */
  843.         printf("%c\b", ind[feedback++ % 4]);    /* Show activity */
  844.  
  845.         while (millitime() <= time) {
  846.             len = (*sip->si_sif->sif_poll)(sip->si_devdata, tmpbuf);
  847.             if (len < used_size)
  848.                 continue;
  849.             if (in->arp_ea.arp_pro != ETHERPUP_IPTYPE)
  850.                 continue;
  851.             if (out->arp_ea.arp_op == ARPOP_REQUEST) {
  852.                 if (in->arp_eh.ether_type != ETHERPUP_ARPTYPE)
  853.                     continue;
  854.                 if (in->arp_ea.arp_op != ARPOP_REPLY)
  855.                     continue;
  856.                 if (arp_spa(&in->arp_ea).s_addr !=
  857.                     arp_tpa(&out->arp_ea).s_addr)
  858.                     continue;
  859.                 if (count >= WAITCNT) {
  860.                     printf("Found at ");
  861.                     ether_print(&arp_sha(&in->arp_ea));
  862.                 }
  863.                 sain->sain_hisether = arp_sha(&in->arp_ea);
  864.                 return;
  865.             } else {        /* Reverse ARP */
  866.                 if (in->arp_eh.ether_type !=ETHERPUP_REVARPTYPE)
  867.                     continue;
  868.                 if (in->arp_ea.arp_op != REVARP_REPLY)
  869.                     continue;
  870.                 if (bcmp((caddr_t)&arp_tha(&in->arp_ea),
  871.                     (caddr_t)&arp_tha(&out->arp_ea), 
  872.                     sizeof (struct ether_addr)) != 0)
  873.                     continue;
  874.  
  875.                 printf("Using IP Address ");
  876.                 inet_print(arp_tpa(&in->arp_ea));
  877.  
  878.                 sain->sain_myaddr = arp_tpa(&in->arp_ea);
  879.                 /* short circuit first ARP */
  880.                 sain->sain_hisaddr = arp_spa(&in->arp_ea);
  881.                 sain->sain_hisether = arp_sha(&in->arp_ea);
  882.                 return;
  883.             }
  884.         }
  885.         delay = delay * 2;    /* Double the request delay */
  886.  
  887.         if (delay > 64)        /* maximum delay is 64 seconds */
  888.             delay = 64;
  889.  
  890.         (*sip->si_sif->sif_reset)(sip->si_devdata);
  891.     }
  892.     /* NOTREACHED */
  893. d107 3
  894. a109 6
  895.  
  896. /*
  897.  * Output an IP packet
  898.  * Cause ARP to be invoked if necessary
  899.  */
  900. ip_output(sip, buf, len, sain, tmpbuf)
  901. d111 1
  902. a111 3
  903.     caddr_t buf, tmpbuf;
  904.     short len;
  905.     register struct sainet *sain;
  906. d113 2
  907. a114 18
  908.     register struct ether_header *eh;
  909.     register struct ip *ip;
  910.  
  911.     eh = (struct ether_header *)buf;
  912.     ip = (struct ip *)(buf + sizeof(struct ether_header));
  913.     if (ip->ip_dst.s_addr != sain->sain_hisaddr.s_addr) {
  914.         sain->sain_hisaddr.s_addr = ip->ip_dst.s_addr;
  915.         arp(sip, sain, tmpbuf);
  916.     }
  917.     eh->ether_type = ETHERPUP_IPTYPE;
  918.     eh->ether_shost = sain->sain_myether;
  919.     eh->ether_dhost = sain->sain_hisether;
  920.     /* checksum the packet */
  921.     ip->ip_sum = 0;
  922.     ip->ip_sum = ipcksum((caddr_t)ip, sizeof (struct ip));
  923.     if (len < ETHERMIN+sizeof(struct ether_header))
  924.         len = ETHERMIN+sizeof(struct ether_header);
  925.     return (*sip->si_sif->sif_xmit)(sip->si_devdata, buf, len);
  926. d116 2
  927. a117 1
  928.  
  929. d119 11
  930. a129 4
  931.  * Check incoming packets for IP packets
  932.  * addressed to us. Also, respond to ARP packets
  933.  * that wish to know about us.
  934.  * Returns a length for any IP packet addressed to us, 0 otherwise.
  935. d131 1
  936. a131 1
  937. ip_input(sip, buf, sain)
  938. d133 1
  939. a133 2
  940.     caddr_t buf;
  941.     register struct sainet *sain;
  942. d135 102
  943. a236 4
  944.     register short len;
  945.     register struct ether_header *eh;
  946.     register struct ip *ip;
  947.     register struct ether_arp *ea;
  948. d238 1
  949. a238 32
  950.     len = (*sip->si_sif->sif_poll)(sip->si_devdata, buf);
  951.     eh = (struct ether_header *)buf;
  952.     if (eh->ether_type == ETHERPUP_IPTYPE &&
  953.         len >= sizeof(struct ether_header)+sizeof(struct ip)) {
  954.         ip = (struct ip *)(buf + sizeof(struct ether_header));
  955.         if (ip->ip_dst.s_addr != sain->sain_myaddr.s_addr) 
  956.             return (0);
  957.         return (len);
  958.     }
  959.     if (eh->ether_type == ETHERPUP_ARPTYPE &&
  960.         len >= sizeof(struct ether_header)+sizeof(struct ether_arp)) {
  961.         ea = (struct ether_arp *)(buf + sizeof(struct ether_header));
  962.         if (ea->arp_pro != ETHERPUP_IPTYPE) 
  963.             return (0);
  964.         if (arp_spa(ea).s_addr == sain->sain_hisaddr.s_addr)
  965.             sain->sain_hisether = arp_sha(ea);
  966.         if (ea->arp_op == ARPOP_REQUEST &&
  967.             arp_tpa(ea).s_addr == sain->sain_myaddr.s_addr) {
  968.             ea->arp_op = ARPOP_REPLY;
  969.             eh->ether_dhost = arp_sha(ea);
  970.             eh->ether_shost = sain->sain_myether;
  971.             arp_tha(ea) = arp_sha(ea);
  972.             arp_tpa(ea) = arp_spa(ea);
  973.             arp_sha(ea) = sain->sain_myether;
  974.             arp_spa(ea) = sain->sain_myaddr;
  975.             (*sip->si_sif->sif_xmit)(sip->si_devdata, buf, 
  976.                         sizeof(struct arp_packet));
  977.         }
  978.         return (0);
  979.     }
  980.     return (0);
  981. }
  982. d240 8
  983. a247 7
  984. /*
  985.  * Return the host portion of an internet address.
  986.  */
  987. in_lnaof(in)
  988.     struct in_addr in;
  989. {
  990.     register u_long i = ntohl(in.s_addr);
  991. d249 68
  992. a316 7
  993.     if (IN_CLASSA(i))
  994.         return ((i)&IN_CLASSA_HOST);
  995.     else if (IN_CLASSB(i))
  996.         return ((i)&IN_CLASSB_HOST);
  997.     else
  998.         return ((i)&IN_CLASSC_HOST);
  999. }
  1000. d318 84
  1001. a401 11
  1002. /*
  1003.  * Compute one's complement checksum
  1004.  * for IP packet headers 
  1005.  */
  1006. ipcksum(cp, count)
  1007.     caddr_t    cp;
  1008.     register unsigned short    count;
  1009. {
  1010.     register unsigned short    *sp = (unsigned short *)cp;
  1011.     register unsigned long    sum = 0;
  1012.     register unsigned long    oneword = 0x00010000;
  1013. d403 29
  1014. a431 6
  1015.     count >>= 1;
  1016.     while (count--) {
  1017.         sum += *sp++;
  1018.         if (sum >= oneword) {        /* Wrap carries into low bit */
  1019.             sum -= oneword;
  1020.             sum++;
  1021. d434 6
  1022. a439 16
  1023.     return (~sum);
  1024. }
  1025.  
  1026. inet_print(s)
  1027.     struct in_addr s;
  1028. {
  1029.     int    len = 2;
  1030.  
  1031.     printf("%d.%d.%d.%d = ", s.S_un.S_un_b.s_b1, s.S_un.S_un_b.s_b2,
  1032.         s.S_un.S_un_b.s_b3, s.S_un.S_un_b.s_b4);
  1033.  
  1034.     printhex(s.S_un.S_un_b.s_b1, len);
  1035.     printhex(s.S_un.S_un_b.s_b2, len);
  1036.     printhex(s.S_un.S_un_b.s_b3, len);
  1037.     printhex(s.S_un.S_un_b.s_b4, len);
  1038.     printf("\n");
  1039. a441 7
  1040. ether_print(ea)
  1041.     struct ether_addr *ea;
  1042. {
  1043.     register u_char *p = &ea->ether_addr_octet[0];
  1044.  
  1045.     printf("%x:%x:%x:%x:%x:%x\n", p[0], p[1], p[2], p[3], p[4], p[5]);
  1046. }
  1047. @
  1048.  
  1049.  
  1050. 1.1
  1051. log
  1052. @Initial revision
  1053. @
  1054. text
  1055. @d12 11
  1056. a22 11
  1057. #include "dev/saio.h"
  1058. #include "h/socket.h"
  1059. #include "dev/if.h"
  1060. #include "h/in.h"
  1061. #include "dev/if_ether.h"
  1062. #include "h/in_systm.h"
  1063. #include "h/ip.h"
  1064. #include "h/udp.h"
  1065. #include "h/sainet.h"
  1066. #include "h/sunromvec.h"
  1067. #include "sun3/cpu.addrs.h"
  1068. d25 1
  1069. a25 1
  1070. #include "h/tftp.h"
  1071. d27 2
  1072. d69 2
  1073. a70 2
  1074.     register struct saioreq *sip;
  1075.     struct bootparam *bp;
  1076. d72 150
  1077. a221 14
  1078.     register struct tftpglob *tf = TFTPBASE;
  1079.     register struct tftp_pack *out = &tf->tf_out;
  1080.     register struct tftp_pack *in = (struct tftp_pack *)tf->tf_tmpbuf;
  1081.     register char *p, *q, *x;
  1082.     register short i, len;
  1083.     int autoboot = 0;
  1084.     int firsttry = 0;
  1085.     int feedback = 0;
  1086.     int time, xcount, locked, retry;
  1087.     char    *ind = "-\\|/";
  1088.  
  1089.     if (sip->si_unit == 0)
  1090.                 autoboot = 1;    /* if unit # is 0, this is an autoboot */
  1091. top:
  1092. d223 1
  1093. a223 13
  1094.      * Initialize IP and UDP headers
  1095.      */
  1096.     out->tf_ip.ip_v = IPVERSION;
  1097.     out->tf_ip.ip_hl = sizeof (struct ip) / 4;
  1098.     out->tf_ip.ip_ttl = MAXTTL;
  1099.     out->tf_ip.ip_p = IPPROTO_UDP;
  1100.     out->tf_udp.uh_sport =  (millitime() & 1023) + 1024;
  1101.     out->tf_udp.uh_dport =  IPPORT_TFTP;
  1102.     out->tf_udp.uh_sum =  0;        /* no checksum */
  1103.      
  1104.     /* 
  1105.      * Set src and dst host addresses
  1106.      * Dst host is argument with our net number plugged in
  1107. d225 2
  1108. a226 2
  1109.     out->tf_ip.ip_src = tf->tf_inet.sain_myaddr;
  1110.  
  1111. d228 4
  1112. a231 11
  1113.     /*
  1114.      * Since the tftpglob at TFTPBASE has been copied, we assume the
  1115.      * destination address is all set up
  1116.      */
  1117.     if (autoboot && firsttry == 0) {
  1118.             out->tf_ip.ip_dst.s_addr = tf->tf_inet.sain_hisaddr.s_addr;
  1119.     } else if (autoboot && firsttry > 0) {
  1120.         out->tf_ip.ip_dst.s_addr = -1;
  1121.     } else {
  1122.         out->tf_ip.ip_dst.s_addr = out->tf_ip.ip_src.s_addr +
  1123.                 sip->si_unit  - in_lnaof(out->tf_ip.ip_src);
  1124. a232 11
  1125. #else
  1126.     printf("Downloading \"%s\" from tftp server at ", bp->bp_name); 
  1127.     inet_print(out->tf_ip.ip_dst);
  1128. #endif
  1129.  
  1130.     ++firsttry;
  1131.     locked = 0;
  1132.     retry = 0;
  1133.     tf->tf_block = 1;
  1134.     tf->tf_data = (char *)KERNEL_START;
  1135.  
  1136. d234 1
  1137. a234 1
  1138.      * Create the TFTP Read Request packet 
  1139. d236 17
  1140. a252 27
  1141.     out->tf_tftp.th_opcode = RRQ;
  1142.     p = out->tf_tftp.th_stuff;
  1143.     q = bp->bp_name;
  1144.     while (*p++ = *q++) {
  1145.         /* void */ ;
  1146.     }
  1147.     q = "octet";
  1148.     while (*p++ = *q++)
  1149.         ;
  1150.     out->tf_udp.uh_ulen = sizeof (struct udphdr) + 2 +
  1151.         (p - out->tf_tftp.th_stuff);
  1152.     out->tf_ip.ip_len = sizeof (struct ip) +
  1153.         out->tf_udp.uh_ulen;
  1154.     
  1155.     time = 0;
  1156.     for (xcount = 0; xcount < 5;) {
  1157.         if (millitime() - time >= REXMIT_MSEC) {
  1158.             time = millitime();
  1159.             printf("%c\b", ind[feedback++ % 4]); /* Show activity */
  1160.             if (ip_output(sip, (caddr_t)out, out->tf_ip.ip_len +
  1161.                 sizeof (struct ether_header), &tf->tf_inet,
  1162.                 tf->tf_tmpbuf))
  1163.                 printf("X\b");
  1164.             if (locked == 0 || retry > 15)
  1165.                 xcount++;
  1166.             else 
  1167.                 retry++;
  1168. d254 4
  1169. a257 22
  1170.         len = ip_input(sip, (caddr_t)in, &tf->tf_inet);
  1171.         if (len < TFTPHDRLEN)
  1172.             continue;
  1173.         if (in->tf_ip.ip_p != IPPROTO_UDP ||
  1174.             in->tf_udp.uh_dport != out->tf_udp.uh_sport) 
  1175.             continue;
  1176.         if (locked &&
  1177.                     out->tf_ip.ip_dst.s_addr != in->tf_ip.ip_src.s_addr)                                continue;
  1178.         if (in->tf_tftp.th_opcode == ERROR) {
  1179.             if (autoboot && tf->tf_block == 1)
  1180.                 continue;
  1181.             if (in->tf_tftp.th_code < 0 ||
  1182.                 in->tf_tftp.th_code > sizeof(tftp_errs)/sizeof(char *)){
  1183.                 printf("tftp: Unknown error 0x%x\n",
  1184.                     in->tf_tftp.th_code);
  1185.             } else {
  1186.                 printf("tftp: %s @@ block %d\n",
  1187.                     tftp_errs[in->tf_tftp.th_code], tf->tf_block);
  1188.             }
  1189.             if (autoboot)
  1190.                 goto top;
  1191.             return (-1);
  1192. d259 5
  1193. a263 11
  1194.         if (in->tf_tftp.th_opcode != DATA ||
  1195.             in->tf_tftp.th_block != tf->tf_block) 
  1196.             continue;
  1197.         /*
  1198.          * Here if we have an in sequence DATA packet
  1199.          */
  1200.         if (tf->tf_block == 1) {    /* lock on to server and port */
  1201.             out->tf_udp.uh_dport = in->tf_udp.uh_sport;
  1202.             if (autoboot) 
  1203.                 out->tf_ip.ip_dst = in->tf_ip.ip_src;
  1204.             locked = 1;
  1205. d265 30
  1206. a294 28
  1207.         /*
  1208.          * Swallow data
  1209.          */
  1210.         len = in->tf_udp.uh_ulen - (sizeof(struct udphdr) + 4);
  1211.         if (len) {
  1212.             bcopy(in->tf_tftp.th_data, tf->tf_data, len);
  1213.             tf->tf_data += len;
  1214.         }
  1215.         /*
  1216.          * Send ACK 
  1217.          */
  1218.         xcount = 0;
  1219.         retry = 0;
  1220.         out->tf_tftp.th_opcode = ACK;
  1221.         out->tf_tftp.th_block = tf->tf_block++;
  1222.         out->tf_udp.uh_ulen = sizeof (struct udphdr) + 4;
  1223.         out->tf_ip.ip_len = sizeof (struct ip) + out->tf_udp.uh_ulen;
  1224.         time = millitime();
  1225.         printf("%c\b", ind[feedback++ % 4]);    /* Show activity */
  1226.         if (ip_output(sip, (caddr_t)out, out->tf_ip.ip_len +
  1227.             sizeof (struct ether_header), &tf->tf_inet,
  1228.             tf->tf_tmpbuf))
  1229.             printf("X\b");
  1230.         if (len < SEGSIZE) {     /* end of file */
  1231.             printf("Downloaded %d bytes from tftp server.\n\n",
  1232.                 tf->tf_data - KERNEL_START);
  1233.             return (KERNEL_START);
  1234.         }
  1235. d296 7
  1236. a302 4
  1237.     printf("tftp: time-out.\n");
  1238.     if (autoboot)
  1239.         goto top;
  1240.     return (-1);
  1241. @
  1242.